home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / T / TE32K Folder / TE32K Documentation next >
Encoding:
Text File  |  1993-02-11  |  17.9 KB  |  433 lines  |  [TEXT/????]

  1.             The TE32K TextEdit Replacement
  2.             ==============================
  3.  
  4.                 by Roy Wood
  5.                 122 Britannia Avenue
  6.               London, Ontario, Canada
  7.                   N6H 2J5
  8.  
  9.                 (519) 438-3177
  10.  
  11.          rrwood@canrem.com, rrwood@canrem.uucp
  12.  
  13.  
  14.  
  15.  
  16. Contents:
  17. =========
  18.  
  19. Introduction                 - What's this darn thing good for?
  20. Legal Stuff                    - Oh, no....
  21. Using TE32K                    - How do I use it anyway?
  22. TE32K Data Structures        - What's a TE32KRec?
  23. TE32K Interface Calls        - I have to do what?!?!?!
  24. TE32K Demo                    - Make me a believer!
  25. TE32K Version History        - In the beginning....
  26. The Future                    - Vapourware-wannabe stuff
  27.  
  28.  
  29.  
  30. Introduction:
  31. =============
  32.  
  33. TE32K is designed to be a more-or-less “plug in” replacement for the Macintosh Toolbox TextEdit package.  The major difference between the two editor packages is that TE32K allows for the manipulation of text-files LARGER than 32K.  There are a few other differences as well, most of which are shortcomings due to laziness on my part, but since this source code is provided to you gratis, please feel free to modify it in whatever twisted way your warped little heart desires.  If you do improve it in any way, please be kind enough to share your work with the rest of us (i.e. send me a copy so I can keep track of TE32K's current state of evolution!).
  34.  
  35. Note that TE32K is written as a non-OOP C program.  If this is not what you're interested in, I suggest you take a look at the many excellent OOP TextEdit replacement class libraries available via FTP, none of which I can remember the names or locations of right now. (though I do recall that Chris Wysocki wrote one, and I *think* I saw it at ftp.brown.edu, but don't hold me to that)
  36.  
  37. I wrote TE32K since I needed it for rnMac, a Macintosh newsreader I wrote.  Well, I didn't really need it, but it was nice to have, and I wasn't doing anything one afternoon, so.....
  38.  
  39.  
  40.  
  41. Legal Stuff:
  42. ============
  43.  
  44. TE32K is provided free of charge, since no-one will ever pay me anything for it anyway.  However, if you do use TE32K in a piece of software which you market, for every copy you sell, you are required to donate $1.00 to the World Wildlife Fund, 90 Eglinton Avenue East, Suite 504, Toronto, Ontario, Canada, M4P 2Z7.  I guess that makes TE32K CharityWare or maybe EcoWare. :)
  45.  
  46.  
  47.  
  48. Using TE32K:
  49. ============
  50.  
  51. TE32K is designed as a source-level replacement for TextEdit.  This means that you will have to compile the “TE32K.c” file along with the rest of your program.  As well, you will have to change all your TextEdit calls to the equivalent TE32K routines, and make sure you pass appropriate-sized parameters (i.e. long's instead of ints, LongRect's instead of Rect's, LongPoints instead of Points, etc.).  The TE32K function calls and data structures are declared in the file “TE32K.h” which you should #include in your source, too.  The data structures and interface calls are described in the following sections.
  52.  
  53. Note that TE32K is not optimized as much as it should be, so the results are sometimes less than perfect (e.g. unnecessary redrawing and flashing).  However, you really can't expect much from CharityWare, can you?  And if it really bothers you, you are more than welcome to fix things up....
  54.  
  55. Warning: the one BIG inconsistency between TE32K and TextEdit is that you have to call TE32KSetFontStuff() to change the font or font-size.  I maintain a table of character widths in the TE32KRec to speed up the screen updates (calling CharWidth() is slooooooow), and if you change the font without telling TE32K, the results will not be what you expected!
  56.  
  57.  
  58. TE32K Data Structures:
  59. ======================
  60.  
  61. TE32K uses a couple of unconventional data stuctures to work its magic; these are defined in the “TE32K.h” header file as follows:
  62.  
  63.  
  64. /* a Rect defined with long's, rather than int's */
  65.  
  66. typedef    struct
  67. {
  68.     long        top,left,bottom,right;
  69.     
  70. } LongRect;
  71.  
  72.  
  73. /* a Point defined with long's rather than int's */
  74.  
  75. typedef    struct
  76. {
  77.     long        h,v;
  78.     
  79. } LongPoint;
  80.  
  81.  
  82. /* the TE32K data structure!  Notice the standard TextEdit field names! */
  83.  
  84. typedef pascal Boolean (*TE32KProcPtr)(void);
  85.  
  86. typedef    struct
  87. {
  88.     LongRect        destRect;    /* the destination rectangle */
  89.     LongRect        viewRect;    /* the view rectangle */
  90.     int            lineHeight;    /* height of a line of text */
  91.     int            fontAscent;    /* the font ascent */
  92.     LongPoint    selPoint;    /* coords of the selection point */
  93.     long            selStart;    /* the start of the selected text */
  94.     long            selEnd;        /* the end of the selected text */
  95.     int            active;        /* active flag */
  96.     TE32KProcPtr    clikLoop;    /* hook for the click-loop routine */
  97.     long            clickTime;    /* time used for double-clicking */
  98.     long            clickLoc;    /* location of last click, maybe */
  99.     int            clikStuff    /* flag for EOL cursor placement */
  100.     long            caretTime;    /* time for blinking cursor */
  101.     int            caretState;    /* state of cursor (visible/invis.) */
  102.     long            teLength;    /* size of edit text */
  103.     Handle        hText;        /* Handle to text */
  104.     int            txFont;        /* the font */
  105.     char            txFace;        /* the font face */
  106.     int            txMode;        /* the text display mode */
  107.     int            txSize;        /* the size of the text */
  108.     int            tabWidth;    /* the width of tabs */
  109.     int            tabChars;    /* if non-zero, used to calculate tabwidth */
  110.     int            maxLineWidth;    /* max width of a line in char's */
  111.     int            crOnly;        /* do Carriage Return only? */
  112.     GrafPtr        inPort;        /* the GrafPort we're in */
  113.     long            nLines;        /* the number of lines of text */
  114.     int            theCharWidths[256];    /* q&d lookup table */
  115.     long            lineStarts[];    /* the line starts array */
  116.     
  117. }     TE32KRec,*TE32KPtr,**TE32KHandle;
  118.  
  119.  
  120.  
  121. If you've done any programming with TextEdit, you'll quickly realize that these data structures are pretty easy to figure out .  Basically, I've just enlarged the relevant field sizes from int's to long's, and thrown away the fields I didn't need.  All the fields of the TE32KRec are named the same as traditional TextEdit fields, so it should be pretty simple to modify your source code to be compatible with TE32K.  The programs I've used it in were written to use TextEdit originally, but it's taken me no more than half an hour to make them compatible with TE32K.  If this seems too much effort for you, maybe you should stick with TextEdit then.
  122.  
  123. Note that the “maxLineWidth” field defines the maximum width in characters that a line may be when word-wrapping is in effect (the default width is 32767 characters).  I added this since my newsreader needed to wrap lines if they were wider than, say, 72 characters.
  124.  
  125. Warning: the one BIG inconsistency between TE32K and TextEdit is that you have to call TE32KSetFontStuff() to change the font or font-size.  I maintain a table of character widths in the TE32KRec to speed up the screen updates (calling CharWidth() is sloooooooow), and if you change the font without telling TE32K, the results will not be what you expected!
  126.  
  127. Also—— the “tabChars” field is normally zero, which means TE32K will honour the tabwidth field.  If tabChars is non-zero, then the tabwidth field is set to the width of tabChars number of spaces in the active font/size/mode/style.
  128.  
  129.  
  130.  
  131. TE32K Interface Calls:
  132. ======================
  133.  
  134. All the public routines are described as follows, with the equivalent TextEdit routine listed below the TE32K function declaration.  The name of each routine is basically the same as the standard TextEdit routine albeit with the “TE” replaced by “TE32K”.  The parameters are pretty much the same as usual too, with the major difference being the use of long's in place of int's, etc.
  135.  
  136.  
  137. void TE32KInit(void);
  138. ---------------------
  139. replaces TEInit
  140.  
  141. Initialize the TE32K scrap Handle
  142.  
  143.  
  144. TE32KHandle TE32KNew(LongRect *destRect,LongRect *viewRect);
  145. ------------------------------------------------------------
  146. replaces TENew
  147.  
  148. Allocate and return a Handle to a new TE32K edit record; destRect and viewRect as per usual
  149.  
  150.  
  151. void     TE32KDispose(TE32KHandle theTE32KHandle);
  152. ----------------------------------------------
  153. replaces TEDispose
  154.  
  155. Dispose of a previously-allocated TE32K record
  156.  
  157.  
  158. void TE32KCalText(TE32KHandle theTE32KHandle);
  159. ----------------------------------------------
  160. TECalText
  161.  
  162. Calculate the lineStarts array for a text record
  163.  
  164.  
  165. void TE32KUseTextHandle(Handle hText,TE32KHandle theTE32KHandle);
  166. -----------------------------------------------------------------
  167. unique to TE32K, courtesy of Dave Platt <dplatt@snulbug.mtview.ca.us>
  168.  
  169. Sets the text handle to hText, discards the old text handle if there was one; saves on memory muddling.  Do not try to DisposeHandle(hText) after passing hText to TE32KUseTextHandle!
  170.  
  171.  
  172. void     TE32KSetText(Ptr theText,long length,TE32KHandle theTE32KHandle);
  173. ----------------------------------------------------------------------
  174. replaces TESetText
  175.  
  176. Set the text of the TE32K record to a copy of the text pointed at by theText, length of which is given by length parameter
  177.  
  178.  
  179. Handle TE32KGetText(TE32KHandle theTE32KHandle);
  180. ------------------------------------------------
  181. replaces TEGetText
  182.  
  183. Returns a copy of the Handle of the text record
  184.  
  185.  
  186. void TE32KUpdate(LongRect *updateRect,TE32KHandle theTE32KHandle);
  187. ------------------------------------------------------------------
  188. replaces TEUpdate
  189.  
  190. Update the display of the text within the specified update rectangle
  191.  
  192.  
  193. void TE32KScroll(long dh,long dv,TE32KHandle theTE32KHandle);
  194. -------------------------------------------------------------
  195. replaces TEScroll
  196.  
  197. Scroll the text display the amount specified by dh and dv
  198.  
  199.  
  200. void TE32KActivate(TE32KHandle theTE32KHandle);
  201. -----------------------------------------------
  202. replaces  TEActivate
  203.  
  204. Activate the text record
  205.  
  206.  
  207. void TE32KDeactivate(TE32KHandle theTE32KHandle);
  208. -------------------------------------------------
  209. replaces TEDeactivate
  210.  
  211. Deactivate the text record
  212.  
  213.  
  214. void TE32KIdle(TE32KHandle theTE32KHandle);
  215. -------------------------------------------
  216. replaces TEIdle
  217.  
  218. Call this to blink the cursor
  219.  
  220.  
  221. void TE32KKey(unsigned char theChar,TE32KHandle theTE32KHandle);
  222. ----------------------------------------------------------------
  223. replaces TEKey
  224.  
  225. Process the keystroke contained in theChar.  Note that even arrow keys and shifted arrow key combinations are correctly handled by TE32K.
  226.  
  227.  
  228. void TE32KClick(Point thePt,unsigned char extend,TE32KHandle theTE32KHandle);
  229. -----------------------------------------------------------------------------
  230. replaces TEClick
  231.  
  232. Respond to a mouse-down event in the view rectangle, extend indicates whether the shift-key was depressed and thus whether the user is selecting a range of text
  233.  
  234.  
  235. void TE32KSetSelect(long selStart,long selEnd,TE32KHandle theTE32KHandle);
  236. --------------------------------------------------------------------------
  237. replaces TESetSelect
  238.  
  239. Set the selection range of the text record
  240.  
  241.  
  242. OSErr TE32KToScrap(void);
  243. -------------------------
  244. replaces TEFromScrap
  245.  
  246. Copy the TE32K scrap to the desktop/clipboard scrap
  247.  
  248.  
  249. OSErr TE32KFromScrap(void);
  250. ---------------------------
  251. replaces TEFromScrap
  252.  
  253. Copy the desktop/clipboard scrap to the TE32K scrap
  254.  
  255.  
  256. void TE32KCopy(TE32KHandle theTE32KHandle);
  257. -------------------------------------------
  258. replaces TECopy
  259.  
  260. Copy the selected range of text to the TE32K scrap
  261.  
  262.  
  263. void TE32KCut(TE32KHandle theTE32KHandle);
  264. ------------------------------------------
  265. replaces TECut
  266.  
  267. Cut the selected range of text to the TE32K scrap
  268.  
  269.  
  270. void TE32KDelete(TE32KHandle theTE32KHandle);
  271. ---------------------------------------------
  272. replaces TEDelete
  273.  
  274. Delete the selected range of text to the TE32K scrap
  275.  
  276.  
  277. void TE32KInsert(Ptr textPtr,long length,TE32KHandle theTE32KHandle);
  278. ---------------------------------------------------------------------
  279. replaces TEInsert
  280.  
  281. Insert a block of text at the current cursor location within the text record, do all necessary lineStart calculations
  282.  
  283.  
  284. void TE32KPaste(TE32KHandle theTE32KHandle);
  285. --------------------------------------------
  286. replaces TEPaste
  287.  
  288. Paste the TE32K scrap to the current cursor location
  289.  
  290.  
  291. Handle TE32KScrapHandle(void);
  292. ------------------------------
  293. replaces TEScrapHandle
  294.  
  295. Returns a copy of the Handle to the TE32K scrap
  296.  
  297.  
  298. long TE32KGetScrapLen(void);
  299. ----------------------------
  300. replaces TEGetScrapLen
  301.  
  302. Returns the length of the TE32K scrap
  303.  
  304.  
  305. void TE32KSetScrapLen(long length);
  306. -----------------------------------
  307. replaces TESetSCrapLen
  308.  
  309. Set the length of the TE32K scrap if you've changed its length
  310.  
  311.  
  312. void TE32KGetPoint(long selIndex,LongPoint *selPt,TE32KHandle theTE32KHandle);
  313. ------------------------------------------------------------------------------
  314. replaces TEGetPoint
  315.  
  316. Returns in selPt the coordinates of the character specified by selIndex.  
  317.  
  318. Since there is an ambiguity regarding the coordinates of the index at the end of a wrapped line, there is a necessary black magic parameter: clikStuff.  If the clikStuff field of the TE32KHandle is non-zero, the coordinates returned correspond to the end of the previous line; otherwise the coordinates returned are the start of the next line.  The clikStuff field is automatically reset to zero after every call to TE32KGetPoint, too.  
  319.  
  320. Confused?  Well, TE32KClick and TE32KKey take care of cursor placement most of the time anyway, so don't worry about it.
  321.  
  322.  
  323. long TE32KGetOffset(LongPoint *selPt,TE32KHandle theTE32KHandle);
  324. -----------------------------------------------------------------
  325. replaces TEGetOffset
  326.  
  327. Returns the index to the character at the coordinates specified by selPt
  328.  
  329.  
  330. void TE32KSelView(TE32KHandle theTE32KHandle);
  331. ----------------------------------------------
  332. replaces TESelView
  333.  
  334. Scroll the cursor into view if it's not already visible
  335.  
  336.  
  337. void TE32KSetFontStuff(int font,int face,int mode,int size,TE32KHandle theTE32KHandle);
  338. ---------------------------------------------------------------------------------------
  339. unique to TE32K
  340.  
  341. Use to set the font, face, mode, and size of the text record and update the quick-and-dirty table of character widths used in word-wrapping calculations.  If you change the fields of the TE32KHandle on your own, things will get nasty!
  342.  
  343. If the (**theTE32KHandle).tabChars field is non-zero, the tabwidth field is modified so that (**theTE32KHandle).tabwidth = (**theTE32KHandle).tabChars * CharWidth(' ') in the new font size/style.  If the (**theTE32KHandle).tabChars field is zero the tabwidth remains unchanged.  You decide which one you like (I prefer to set (**theTE32KHandle).tabChars = 8, myself).
  344.  
  345.  
  346. TE32KAutoView(char autoView, TE32KHandle theTE32KHandle);
  347. ---------------------------------------------------------
  348. replaces TEAutoView
  349.  
  350. Use to turn on/off automatic scrolling.  If autoView is TRUE, autoView scrolling is enabled; if autoView is FALSE, such scrolling is disabled.
  351.  
  352.  
  353.  
  354. void SetLongRect(LongRect *,long,long,long,long);
  355. -------------------------------------------------
  356. unique to TE32K
  357.  
  358. Use to set the left, top, right, bottom of a LongRect; similar to SetRect
  359.  
  360.  
  361. void LongRectToRect(LongRect *,Rect *);
  362. -------------------------------------------------
  363. unique to TE32K
  364.  
  365. Convert a LongRect to a simple Rect, clipping the size if necessary
  366.  
  367.  
  368. void RectToLongRect(Rect *,LongRect *);
  369. -------------------------------------------------
  370. unique to TE32K
  371.  
  372. Convert a Rect to a LongRect
  373.  
  374.  
  375.  
  376. void OffsetLongRect(LongRect *, long, long)
  377. -------------------------------------------
  378. unique to TE32K, courtesy of Dave Platt <dplatt@snulbug.mtview.ca.us>
  379.  
  380. Offset a LongRect
  381.  
  382.  
  383. Phew, still with me?  Well, as promised, they're pretty much identical to their TextEdit counterparts, and modifying your source to be compatible should be a breeze, more or less (Ha!).  Just watch out for the use of long's in place of int's. (And yes, I know you don't like the way I keep inflecting “long” to indicate plurality.  And I agree; it does make me look like a dummy who doesn't know anything about the possessive case, but my Canadian Writer's Handbook says that it's okay to use an apostrophe to indicate plurality for short little weird words, so I'm going to continue doing it.)
  384.  
  385.  
  386. TE32K Demo:
  387. ===========
  388.  
  389. So, you'd like to actually see TE32K in action?  Well, with the source code for TE32K, I've included a little application that allows you to open and edit text files using TE32K instead of TextEdit.  Heck, I even include the source code so you can muck around with it yourself!  It was written using Symantec's Think C, version 5.0.2 (or whatever the version number is).  I used the demo to write this document, so it sort of even works!
  390.  
  391.  
  392.  
  393. -Roy Wood, December 31, 1992.
  394.  
  395.  
  396.  
  397.  
  398.  
  399. TE32K Version History:
  400. ======================
  401.  
  402. V 1.0
  403. -----
  404. • initial release
  405.  
  406. V 1.1
  407. -----
  408. • corrected return type for TE32KFromScrap and TE32KToScrap so now they are OSErr's instead of void's
  409. • optimized TE32KInsert so it calls TE32KKey to insert single characters
  410. • enabled clicking and cursor movement to the end of word-wrapped lines
  411. • fixed a bug in the TE32KInsert code that failed to initialize sizeTE32KHandle, and thereby caused some nasty heap-trashing to occur
  412. • added capability to wrap lines after a specific number of characters (maxLineWidth field in TE32KRec)
  413. • removed a number of declarations of unused variables from routines (thanks to Teddy Slottow <edward@Athena.MIT.EDU>)
  414. • added OffsetLongRect() routine, courtesy of Dave Platt <dplatt@snulbug.mtview.ca.us>
  415. • tinkered with TE32KSelView logic to enable horizontal movement to show cursor
  416. • removed from many routines a nasty line of code that *could* store a '\r' past the end of the text handle  (these were left over from debugging and should have been removed long ago—— thanks again Dave)
  417. • made sure the port was set before trying to scroll text (many routines needed to have this done)
  418. • added Dave Platt's TE32KUseTextHandle routine
  419. • removed the useless TE32KCalTextFrom and TE32KCalTextFromTo routines
  420. • made sure that TE32KCalText always sets the nLines field
  421. • fiddled with things so that TE32K recognizes '\n' as well as '\r' characters as EOL's
  422. • added the tabChars field and logic
  423. • fixed a bug in the TE32KCalText routine that neglected to expand the size of the TE32KHandle when adding the final lineStart
  424.  
  425.  
  426.  
  427. The Future:
  428. ===========
  429.  
  430. My biggest gripe is that unnecessary screen updates occur.  There are lots of special cases that I could/should watch for, in which better update handling could/should be done (e.g. type-over of single characters).  As to when I do this, well.....
  431.  
  432. Also, it might be nice if all the TE32K functions returned some sort of an error code (OSErr) if, say, a memory error occurs.  This even sounds easy to do!
  433.